iT邦幫忙

2024 iThome 鐵人賽

DAY 4
1

編譯與直譯

只要學過計算機概論,大抵都對編譯與直譯有基本的概念。

常會有人把程式語言分類爲編譯式語言、直譯式語言兩類,其實這並不嚴謹,編譯與直譯並非形容「語言」,而是形容「語言的執行方式」。

舉例來說, C 語言通常被編譯成機器碼執行,但它也可以直譯執行,例如 c4 就是個極簡 C 語言(子集)直譯器,才幾百行而已。

再舉個例子, Kotlin 官方就支援多種執行方式,可以編譯到機器碼、 JVM 字節碼、乃至於轉譯成 JavaScript 再交由 JavaScript 引擎執行。硬要將它歸類為編譯式或直譯式都不對,唯有把程式如何執行在機器上給具體描述出來,才有意義。

基本上,一個語言能被編譯,那幾乎都能被直譯,因為寫直譯器比編譯器要容易得多。而如 Python/Ruby/JavaScript 等動態語言則很難完全被編譯,即使真要編譯,由於動態語言中一個物件是否擁有某個方法是無法在編譯期判定的,所以在編譯出的執行檔中,勢必得加入厚重的運行時來即時維護物件資料、判定物件類型,但如此一來,還能算是編譯嗎?

總的來說,編譯跟直譯是很粗略的分類,要知道一份程式是如何執行的,終究得深入其編譯時跟運行時的細節才行。當吾人說某語言是編譯執行,往往代表其運行時相對較小,反之若說某語言是直譯執行,代表其含有沈重的運行時(通常得附帶整個直譯器)。

什麼語言容易自舉

帶有沈重運行時的語言難以自舉。以 Python 為例,它的官方實作是用 C 寫的直譯器 CPython。在這個基礎之上,能透過寫 Python 完成自舉嗎?如果用 Python 寫了個 Python 直譯器,該直譯器仍然得運行在 CPython 上,兩層直譯執行會得到一個很慢的直譯器,而且無法擺脫 CPython。

要擺脫 CPython ,就得是用 Python 寫出 Python 編譯器才行,以此編譯器將自身源碼轉為機器碼,就不再依賴 CPython 了。但前一節提到的物件維護運行時怎麼要怎麼加進去呢?有兩種思路:

  1. 手寫真言來實作運行時。
  2. 定義一個不需要運行時的 Python 子集,用這個子集來寫運行時。

不管哪一種做法都需要額外的開發成本。

除了動態語言的物件/類型維護,垃圾搜集也是需要運行時的語言特性。有些語言如 Bash, JavaScript 還支援 eval 這種動態執行程式碼的函數,不把整個直譯器/編譯器包進編譯結果還真支援不了。

編譯時期的語法特性如模式匹配、和類型(sum type)以及各種語法糖都是編譯期(語法、語義分析)就處理完的,跟是否容易自舉的關係不大。當然,語言的能力越強,編譯器越複雜,但語言能力越強,編譯器又越好寫,該如何完成特性的迭代開發,這其中的折衷,大概也是自舉的樂趣所在吧!

TODO: 此節應補圖

小記:本章不少內容屬貧道自行推想,有錯請不吝賜教。


上一篇
離塵第一步:自舉
下一篇
結丹流程概覽(通用編譯流程)
系列文
離塵指引.卷之一.試結丹:程式語言自舉36
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言